/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sdc;

import java.util.List;
import java.util.logging.Level;
import sdc.topology.BAmodelMaker;
import sdc.net.router.*;
import sdc.net.server.comp.*;
import sdc.component.type.*;
import sdc.net.server.appli.*;
import sdc.event.*;
import sdc.utility.MersenneTwisterRNG;
import sdc.utility.PropertyManager;
import sdc.utility.LoggingManager;

/**
 *
 * @author masa
 * @version 1.0.1
 */
public class Simulation {

    final static String version = "1.0.1";

    public static void main(String args[]) {

        LoggingManager.logging(Level.INFO, "VERSION="+version+" Simulation start...", new Throwable());

        int routerNum = PropertyManager.getValueAsInteger("RouterNum");
        RouterFactory.createRouters(routerNum);

        new BAmodelMaker(RouterManager.INSTANCE).makeTopology(PropertyManager.getValueAsInteger("LinkNum"));

        RouterManager.INSTANCE.initAllRoutingTables();

        int componentTypeNum = PropertyManager.getValueAsInteger("ComponentTypeNum");
        double minWL = PropertyManager.getValueAsDouble("MinWorkload");
        double maxWL = PropertyManager.getValueAsDouble("MaxWorkload");
        double rateOfSLA = PropertyManager.getValueAsDouble("RateOfSLA");

        ComponentTypeFactory.createComponentTypes(rateOfSLA, componentTypeNum, minWL, maxWL);

        int serverNum = PropertyManager.getValueAsInteger("ComponentServerNum");
        double defaultCapacity = PropertyManager.getValueAsDouble("ComponentServerDefaultCapacity");
        int classNum = PropertyManager.getValueAsInteger("ComponentServerClassNum");
        ComponentServerFactory.createComponentServers(serverNum, defaultCapacity, classNum);

        int beginningComponentNum = PropertyManager.getValueAsInteger("BeginningComponentNum");
        ComponentFactory.createComponents(beginningComponentNum);

        int maxAppServerNum = PropertyManager.getValueAsInteger("ApplicationServerNum");
        int useComponentNum = PropertyManager.getValueAsInteger("UseComponentNum");
        ApplicationServerFactory.createApplicationServers(maxAppServerNum, useComponentNum);

        //event
        double currentTime;
        MersenneTwisterRNG rnd = MersenneTwisterRNG.INSTANCE;
        currentTime = EventQueue.INSTANCE.getCurrentTime();
        List<ApplicationServer> appList = ApplicationServerManager.INSTANCE.getShuffledList();
        ArrivalEvent arrivalEvent[] = {
            new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(0)), new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(10)),
            new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(1)), new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(11)),
            new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(2)), new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(12)),
            new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(3)), new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(13)),
            new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(4)), new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(14)),
            new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(5)), new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(15)),
            new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(6)), new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(16)),
            new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(7)), new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(17)),
            new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(8)), new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(18)),
            new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(9)), new ArrivalEvent(rnd.nextDouble() * 10.0, appList.get(19)),
        };
        SamplingEvent sampleEvent = new SamplingEvent(5.0, 1);
        ProposalEvent proposalEvent = new ProposalEvent(500.0, serverNum);
        MeetSlaEvent meetSlaEvent = new MeetSlaEvent(500.0);
        ScenarioEvent scenarioEvent[] = {
            new ScenarioEvent(250.0, 4),
            new ScenarioEvent(500.0, 4),
            new ScenarioEvent(750.0, 4),
            new ScenarioEvent(1000.0, 4),
            new ScenarioEvent(1250.0, 4),
            new ScenarioEvent(1500.0, 4),
            new ScenarioEvent(1750.0, 4),
            new ScenarioEvent(2000.0, 4),
            new ScenarioEvent(2250.0, 4),
            new ScenarioEvent(2500.0, 4),
            new ScenarioEvent(2750.0, 4),
            new ScenarioEvent(3000.0, 4),
        };
        for (int i = 0; i < arrivalEvent.length; i++) {
            EventQueue.INSTANCE.addEvent(arrivalEvent[i]);
        }
        EventQueue.INSTANCE.addEvent(sampleEvent);
        //EventQueue.INSTANCE.addEvent(proposalEvent);
        EventQueue.INSTANCE.addEvent(meetSlaEvent);
        for(int i=0;i<scenarioEvent.length;i++){
            EventQueue.INSTANCE.addEvent(scenarioEvent[i]);
        }
        for (int i = 0; i < 20000; i++) {
            try {
                EventQueue.INSTANCE.nextEvent();
            } catch (NullPointerException e) {
                //System.out.println("TAT_ERROR");
            }
            if (currentTime < EventQueue.INSTANCE.getCurrentTime()) {
                currentTime = EventQueue.INSTANCE.getCurrentTime();
            }
        }
        //System.out.println(currentTime);
    }
}
